'use strict';
import * as fs from 'fs';
import stripJsonComments from './strip-json-comments';
import { isArray, isEmpty } from 'lodash';

interface Route {
  [key: string]: string | undefined;
}

class TransformPages {
  private includes: string[];
  private uniPagesJSON: any;
  public routes: Route[];
  public tabbar: string[];
  public routesMap: { [key: string]: Route };

  constructor({ includes, pagesJsonDir }: { includes: string[]; pagesJsonDir: string }) {
    this.includes = includes;
    this.uniPagesJSON = JSON.parse(stripJsonComments(fs.readFileSync(pagesJsonDir, 'utf-8')));
    this.routes = this.getPagesRoutes().concat(this.getSubPackagesRoutes());
    this.tabbar = this.getTabbarRoutes();
    this.routesMap = this.transformPathToKey(this.routes);
  }

  /**
   * 通过读取pages.json文件 生成直接可用的routes
   */
  private getPagesRoutes(pages = this.uniPagesJSON.pages, rootPath: string | null = null): Route[] {
    let routes: Route[] = [];
    for (let i = 0; i < pages.length; i++) {
      const item = pages[i];
      let route: Route = {};
      for (let j = 0; j < this.includes.length; j++) {
        const key = this.includes[j];
        let value = item[key];
        if (key === 'path') {
          value = rootPath ? `/${rootPath}/${value}` : `/${value}`;
        }
        if (key === 'aliasPath' && i === 0 && rootPath === null) {
          route[key] = route[key] || '/';
        } else if (value !== undefined) {
          route[key] = value;
        }
      }
      routes.push(route);
    }
    return routes;
  }

  /**
   * 解析小程序分包路径
   */
  private getSubPackagesRoutes(): Route[] {
    if (!(this.uniPagesJSON && this.uniPagesJSON.subPackages)) {
      return [];
    }
    const subPackages = this.uniPagesJSON.subPackages;
    let routes: Route[] = [];
    for (let i = 0; i < subPackages.length; i++) {
      const subPages = subPackages[i].pages;
      const root = subPackages[i].root;
      const subRoutes = this.getPagesRoutes(subPages, root);
      routes = routes.concat(subRoutes);
    }
    return routes;
  }

  private getTabbarRoutes(): string[] {
    if (!(this.uniPagesJSON && this.uniPagesJSON.tabBar && this.uniPagesJSON.tabBar.list)) {
      return [];
    }
    const tabbar = this.uniPagesJSON.tabBar.list;
    let tabbarMap: string[] = [];
    tabbar.forEach((bar: { pagePath: string }) => {
      tabbarMap.push('/' + bar.pagePath);
    });
    return tabbarMap;
  }

  private transformPathToKey(list: Route[]): { [key: string]: Route } {
    if (!isArray(list) || isEmpty(list)) {
      return {};
    }
    let map: { [key: string]: Route } = {};
    list.forEach((i) => {
      map[i.path] = i;
    });
    return map;
  }
}

interface PluginConfig {
  pagesJsonDir: string;
  includes: string[];
}

function uniReadPagesV3Plugin({ pagesJsonDir, includes }: PluginConfig) {
  let defaultIncludes = ['path', 'aliasPath', 'name'];
  includes = [...defaultIncludes, ...includes];
  let pages = new TransformPages({
    pagesJsonDir,
    includes,
  });
  return {
    name: 'uni-read-pages-v3',
    config(config: any) {
      return {
        define: {
          ROUTES: pages.routes,
          ROUTES_MAP: pages.routesMap,
          TABBAR: pages.tabbar,
        },
      };
    },
  };
}
export default uniReadPagesV3Plugin;
